package com.old.nsi_class.common.payment;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.*;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.old.nsi_class.DB.DateUtils;
import com.wechat.pay.PayUtil;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;

public class WechatPaymentUtil {

    //	1.1 统一下单参数
    public static final String appid = "wx37e5ddff7dc5282e";

    public static final String mch_id = "1498143042";

    public static final String device_info = "WEB";

    public static final String nonce_str = "";

    public static String sign = "";

    public static String out_trade_no = ""; //商户订单号 -自定义时间随机数

    public static final String spbill_create_ip = "192.168.0.198"; //终端IP
    //	String time_start=""; //交易起始时间
//	String time_expire=""; //交易结束时间
    public static final String goods_tag = "";
    public static final String notify_url = "http://data.xinxueshuo.cn/WechatPaymentNotify";//回调地址
    public static String trade_type = "NATIVE";    //	交易类型 原生扫码支付
    public static final String product_id = ""; //商品ID
    public static final String limit_pay = "no_credit";  //指定支付方式 不支持信用卡
    //	String openid=""; //公众号支付用户标识
    public static String scene_info = ""; //场景信息


//	--------------------------------------调用方法----------------------------------------------------------

    //	微信扫码支付：传入商品Id ,价格,商品描述
    public static String WechatGetQR(String body, String total_fee00, String attach) throws Exception {

        //生成参数 nonce_str 随机字符串
        String strTime = DateUtils.onToday();
        String strRandom = WechatPaymentUtil.buildRandom(4) + "";
        String nonce_str = strTime + strRandom;

        // 生成参数 out_trade_no 商户订单号
        //6位随机数
        long random6 = Math.round(Math.random() * 1000000);
        out_trade_no = DateUtils.NowTimeNum() + "-" + random6;

        // 生成 body 商品描述
        body = "新学说 《" + body + "》系列课程";

//      价格单位转换：元 转为 分
        double total_fee01 = Double.parseDouble(total_fee00);
        total_fee01 = total_fee01 * 100;
        int total_fee = (int) total_fee01;

        System.out.println("WechatGetQR.价格:" + total_fee01 + "-" + total_fee01 + "-" + total_fee);


//		统一下单地址：参数封装XML
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);

        packageParams.put("nonce_str", nonce_str);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        packageParams.put("mch_id", mch_id);
        packageParams.put("device_info", device_info);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("total_fee", "" + total_fee + "");
        packageParams.put("appid", appid);
        packageParams.put("appid", appid);

        // 签名验证：sign
        String key = "20180131wxpaylee987654MD897575HM";
        String sign = WechatPaymentUtil.createSign("UTF-8", packageParams, key);
        packageParams.put("sign", sign);
//		发送参数转为XML
        String requestXML = PayUtil.getRequestXml(packageParams);

//		System.out.println("----------------------1---------------------------");
        System.out.println("WechatPaymentUtil: requestXML:" + requestXML);
//		System.out.println("-----------------------1--------------------------");


//		发送请求
        BufferedReader reader = null;
        // 请求返回值
        String strxml = "0";
        int CONNECT_TIMEOUT = 5000;
        String DEFAULT_ENCODING = "UTF-8";
        String urlStr = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        try {
            URL url = new URL(urlStr);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            conn.setConnectTimeout(CONNECT_TIMEOUT);
            conn.setReadTimeout(CONNECT_TIMEOUT);
            //  传入参数
            conn.setRequestProperty("content-type", requestXML);
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
//            if(data == null)
//                data = "";
            writer.write(requestXML);
            writer.flush();
            writer.close();

            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append("\r\n");
            }
            // 返回值
            strxml = sb.toString();
        } catch (IOException e) {
            System.err.println("Payment_api:微信支付第一步，统一下单地址链接失败");
        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
            }
        }

//		System.out.println("-----------------------2--------------------------");
//		System.out.println("WechatPaymentUtil: 请求返回值 strxml:"+strxml);
//		System.out.println("------------------------2-------------------------");


        //--------------------------------------------------------------------------------------------------------------

//        解析返回的 XML
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

        if (null == strxml || "".equals(strxml)) {
            System.err.println("Payment_api:微信支付第一步，解析微信返回XML 失败");
        }

        Map m = new HashMap();
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        org.jdom.Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            org.jdom.Element e = (org.jdom.Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
//            	获取子结点的xml
                v = WechatPaymentUtil.getChildrenText(children);
            }
            m.put(k, v);
        }
        //关闭流
        in.close();
//        值的位置：Map m
//  -------------------------------------------------------------
        //   XML取值
        String urlCode = (String) m.get("code_url");
//		System.out.println("--微信支付二维码："+urlCode);

        String back = "http://qr.liantu.com/api.php?text=" + urlCode;

        return back;
    }


    //	微信HTML5支付：传入商品Id ,价格,商品描述
    public static String WechatHTML5(String body, String total_fee00, String attach, String UserIp) throws Exception {

        //生成参数 nonce_str 随机字符串
        String strTime = DateUtils.onToday();
        String strRandom = WechatPaymentUtil.buildRandom(4) + "";
        String nonce_str = strTime + strRandom;

        // 生成参数 out_trade_no 商户订单号
        //6位随机数
        long random6 = Math.round(Math.random() * 1000000);
        out_trade_no = DateUtils.NowTimeNum() + "-" + random6;

        // 生成 body 商品描述
        body = "新学说 《" + body + "》系列课程";

//      价格单位转换：元 转为 分
        double total_fee01 = Double.parseDouble(total_fee00);
        total_fee01 = total_fee01 * 100;
        int total_fee = (int) total_fee01;

//        交易类型
        trade_type = "MWEB";
//      支付场景信息
        scene_info = "{\"h5_info\": {\"type\":\"wap\",\"wap_url\": \"class.xinxueshuo.cn\",\"wap_name\": \"新学说-在线课堂\"}}";
//      用户IP==UserIp
//		统一下单地址：参数封装XML
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("spbill_create_ip", UserIp);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        packageParams.put("mch_id", mch_id);
        packageParams.put("device_info", device_info);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("total_fee", "" + total_fee + "");
        packageParams.put("scene_info", scene_info);

        // 签名验证：sign
        String key = "20180131wxpaylee987654MD897575HM";
        String sign = WechatPaymentUtil.createSign("UTF-8", packageParams, key);
        packageParams.put("sign", sign);
//		发送参数转为XML
        String requestXML = PayUtil.getRequestXml(packageParams);
//		发送请求
        BufferedReader reader = null;
        // 请求返回值
        String strxml = "0";
        int CONNECT_TIMEOUT = 5000;
        String DEFAULT_ENCODING = "UTF-8";
        String urlStr = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        try {
            URL url = new URL(urlStr);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            conn.setConnectTimeout(CONNECT_TIMEOUT);
            conn.setReadTimeout(CONNECT_TIMEOUT);
            //  传入参数
            conn.setRequestProperty("content-type", requestXML);
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
//            if(data == null)
//                data = "";
            writer.write(requestXML);
            writer.flush();
            writer.close();

            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append("\r\n");
            }
            // 返回值
            strxml = sb.toString();
        } catch (IOException e) {
            System.err.println("Payment_api:微信支付第一步，统一下单地址链接失败");
        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
            }
        }
        System.out.println("WechatPaymentUtil: 请求返回值 strxml:" + strxml);
        //--------------------------------------------------------------------------------------------------------------

//        解析返回的 XML
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

        if (null == strxml || "".equals(strxml)) {
            System.err.println("Payment_api:微信支付第一步，解析微信返回XML 失败");
        }

        Map m = new HashMap();
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        org.jdom.Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            org.jdom.Element e = (org.jdom.Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
//            	获取子结点的xml
                v = WechatPaymentUtil.getChildrenText(children);
            }
            m.put(k, v);
        }
        //关闭流
        in.close();
//        值的位置：Map m
//  -------------------------------------------------------------
        //   XML取值
        String mweb_url = (String) m.get("mweb_url");
//		System.out.println("--微信支付二维码："+urlCode);

        String back = mweb_url;
        return back;
    }

    //	微信支付：小程序 获取openId
    public static String WeChatOpenId(String code, String price, String body, String attach) throws Exception {
//        准备请求参数
//        String MiniAppid = "wxde8e3c3a90198b22";
//        String secret = "7290ba3f803a5bf2d992448884e53058";

        String MiniAppid = "wx239dd449dc72d145";
        String secret = "11a452b00b37ddba1a7543c25a8a30dc";
        String js_code = code;
        String grant_type = "authorization_code";
        //	发送请求
        BufferedReader reader = null;
        // 请求返回值
        String strJson = "0";
        int CONNECT_TIMEOUT = 5000;
        String DEFAULT_ENCODING = "UTF-8";

        System.out.println("js_code:" + js_code);
        String urlStr = "https://api.weixin.qq.com/sns/jscode2session?appid=" + MiniAppid + "&secret=" + secret + "&js_code=" + js_code + "&grant_type=" + grant_type + "";
        try {
            URL url = new URL(urlStr);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            conn.setConnectTimeout(CONNECT_TIMEOUT);
            conn.setReadTimeout(CONNECT_TIMEOUT);
//            传入参数
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
            writer.flush();
            writer.close();

            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append("\r\n");
            }
            // 返回值
            strJson = sb.toString();
        } catch (IOException e) {
            System.err.println("Payment_api:小程序微信支付：失败");
        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
            }
        }
        System.out.println("WechatPaymentUtil: 小程序微信支付：返回strJson:" + strJson);
        Gson gson = new Gson();
        HashMap hashmap = new HashMap();
        JsonObject returnData = new JsonParser().parse(strJson).getAsJsonObject();
        String session_key = returnData.get("session_key").getAsString();
        String openid = returnData.get("openid").getAsString();
        System.out.println("WechatPaymentUtil: 小程序微信支付：session_key:" + session_key + openid);

//        统一下单
        //生成参数 nonce_str 随机字符串
        String strTime = DateUtils.onToday();
        String strRandom = WechatPaymentUtil.buildRandom(4) + "";
        String nonce_str = strTime + strRandom;

        // 生成参数 out_trade_no 商户订单号
        //6位随机数
        long random6 = Math.round(Math.random() * 1000000);
        out_trade_no = DateUtils.NowTimeNum() + "-" + random6;

        // 生成 body 商品描述
//        String body=body;

//        用户Ip
        String UserIp = "192.168.0.122";
        String total_fee00 = price;
//      价格单位转换：元 转为 分
        double total_fee01 = Double.parseDouble(total_fee00);
        total_fee01 = total_fee01 * 100;
        int total_fee = (int) total_fee01;

//        附加信息
//        String attach=attach;
//        交易类型
        trade_type = "JSAPI";
//      支付场景信息
        scene_info = "{\"h5_info\": {\"type\":\"wap\",\"wap_url\": \"class.xinxueshuo.cn\",\"wap_name\": \"新学说-在线课堂\"}}";
//      用户IP==UserIp
//		统一下单地址：参数封装XML
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", MiniAppid);
        packageParams.put("mch_id", mch_id);

        packageParams.put("nonce_str", nonce_str);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("spbill_create_ip", UserIp);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", "JSAPI");
        packageParams.put("mch_id", mch_id);
        packageParams.put("device_info", device_info);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("total_fee", "" + total_fee + "");
        packageParams.put("scene_info", scene_info);
//       jsapi支付
        packageParams.put("openid", openid);

        // 签名验证：sign
        String key = "20180131wxpaylee987654MD897575HM";
        String sign = WechatPaymentUtil.createSign("UTF-8", packageParams, key);
        packageParams.put("sign", sign);
//		发送参数转为XML
        String requestXML = PayUtil.getRequestXml(packageParams);
//		发送请求
        BufferedReader reader02 = null;
        // 请求返回值
        String strxml = "0";
//        int CONNECT_TIMEOUT = 5000;
//        String DEFAULT_ENCODING="UTF-8";
        String urlStr02 = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        try {
            URL url = new URL(urlStr02);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            conn.setConnectTimeout(CONNECT_TIMEOUT);
            conn.setReadTimeout(CONNECT_TIMEOUT);
            //  传入参数
            conn.setRequestProperty("content-type", requestXML);
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
            writer.write(requestXML);
            writer.flush();
            writer.close();

            reader02 = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader02.readLine()) != null) {
                sb.append(line);
                sb.append("\r\n");
            }
            // 返回值
            strxml = sb.toString();
        } catch (IOException e) {
            System.err.println("Payment_api:微信支付第一步，统一下单地址链接失败");
        } finally {
            try {
                if (reader02 != null)
                    reader02.close();
            } catch (IOException e) {
            }
        }
        System.out.println("WechatPaymentUtil: 请求返回值strxml:" + strxml);
        //--------------------------------------------------------------------------------------------------------------
//        解析返回的 XML
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

        if (null == strxml || "".equals(strxml)) {
            System.err.println("Payment_api:微信支付，解析微信返回XML 失败");
        }

        Map m = new HashMap();
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        org.jdom.Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            org.jdom.Element e = (org.jdom.Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
//            	获取子结点的xml
                v = WechatPaymentUtil.getChildrenText(children);
            }
            m.put(k, v);
        }
        //关闭流
        in.close();
//        值的位置：Map m
//  -------------------------------------------------------------

        //   XML取值
        String mweb_url = (String) m.get("mweb_url");
        String backage = "prepay_id=" + (String) m.get("prepay_id");
        // appid
        String timeStamp = Long.toString(System.currentTimeMillis() / 1000);

        String signType = "MD5";
        String key02 = "20180131wxpaylee987654MD897575HM";
        SortedMap<Object, Object> signMap = new TreeMap<Object, Object>();
        signMap.put("appId", MiniAppid);
        signMap.put("timeStamp", timeStamp);
        signMap.put("nonceStr", nonce_str);
        signMap.put("package", backage);
        signMap.put("signType", signType);

        String paySign = WechatPaymentUtil.createSign("UTF-8", signMap, key02);
        System.out.println("paySign:" + sign);
        signMap.put("paySign", paySign);

        String back = "{\"appId\":\"" + MiniAppid + "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\"" + backage + "\",\"signType\":\"MD5\",\"timeStamp\":\"" + timeStamp + "\",\"key\":\"20180131wxpaylee987654MD897575HM\",\"paySign\":\"" + paySign + "\" }";

        return back;
    }


    //	--------------------------------------调用方法----------------------------------------------------------
//	--------------------------------------调用方法----------------------------------------------------------
//	--------------------------------------调用方法----------------------------------------------------------
    //	随机正整数
    public static int buildRandom(int length) {
        int num = 1;
        double random = Math.random();
        if (random < 0.1) {
            random = random + 0.1;
        }
        for (int i = 0; i < length; i++) {
            num = num * 10;
        }
        return (int) ((random * num));
    }


    //  生成sign签名
    public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);
        String sign = WechatPaymentUtil.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }


    //--------------------------------MD5计算----生成sign签名  --------------------------------------------------
    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }


    /**
     * 获取子结点的xml
     *
     * @param children
     * @return String
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator it = children.iterator();
            while (it.hasNext()) {
                org.jdom.Element e = (org.jdom.Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(WechatPaymentUtil.getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        return sb.toString();
    }
    //---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
}
